class IUP_MULTILINE
-- Creates an editable field with one or more lines.

inherit
	IUP_TEXT
		rename
			text as multiline
		redefine
			multiline
		end
	IUP_WIDGET_TEXT_POS
	IUP_WIDGET_TEXT_CARET
		export
			{NONE} all
		end
	IUP_WIDGET_TEXT_SELECTION
		export
			{NONE} all
		end
	IUP_WIDGET_TEXT_SPIN
		export
			{NONE} all
		end

create {ANY}
   multiline

feature {ANY}

	multiline
		-- A new multiline.
		local
			a_multiline, p: POINTER
		do
			a_multiline := int_multiline(p)
			set_widget(a_multiline)
		end

	-- Attributes

	set_auto_hide (state: BOOLEAN)
		-- Auto hide the scroll bars. Default: False. In Windows when 
		-- FORMATTING=False, AUTOHIDE is not supported. In Motif AUTOHIDE is not 
		-- supported.	
		do
			iup_open.set_attribute(Current, "AUTOHIDE", boolean_to_yesno(state))
		end

	set_multiline_caret (lin, col: INTEGER)
		-- (non inheritable): Character position of the insertion point.
		-- The first position, lin or col, is "1". When lin is greater than the 
		-- number of lines, the caret is placed at the last line. When col is 
		-- greater than the number of characters in the given line, the caret is 
		-- placed after the last character of the line.
		-- If the caret is not visible the text is scrolled to make it visible.
		-- In Windows, if the element does not have the focus the returned value 
		-- is the position of the first character of the current selection. The 
		-- caret is only displayed if the element has the keyboard focus, but its 
		-- position can be changed even if not visible. When changed it will also 
		-- change the selection.
		-- See the Notes above if using UTF-8 strings in GTK.
		require
			lin > 0
			col > 0
		local
			str: STRING
		do
			str := lin.out
			str.append_string(",")
			str.append_string(col.out)
			
			iup_open.set_attribute(Current, "CARET", str)
		end

	get_multiline_caret: TUPLE[INTEGER, INTEGER]
		-- The (lin, col) position of the caret.
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "CARET")
			Result := components_of_position (str)
		end

	set_multiline_caret_pos (pos: INTEGER)
		-- (non inheritable): Also the character position of the insertion point, 
		-- but using a zero based character unique index "pos". Useful for 
		-- indexing the VALUE string.
		-- See the Notes above if using UTF-8 strings in GTK.
		do
			iup_open.set_int(Current, "CARETPOS", pos)
		end

	get_multiline_caret_pos: INTEGER
		do
			Result := iup_open.get_int(Current, "CARETPOS")
		end

	get_line_count: INTEGER
		-- (read-only): returns the number of lines in the text.
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "LINECOUNT")

			if str.is_integer then
				Result := str.to_integer
			end
		end

	get_line_value: STRING
		-- (read-only): returns the text of the line where the caret is. It does 
		-- not include the "\n" character.
		do
			Result := iup_open.get_attribute(Current, "LINEVALUE")
		end

	set_scroll_bar (value: STRING)
		-- Associates an automatic horizontal and/or vertical scrollbar to the 
		-- multiline. Can be: "VERTICAL", "HORIZONTAL", "YES" (both) or "NO" 
		-- (none). Default: "YES". For all systems, when SCROLLBAR!=NO the 
		-- natural size will always include its size even if the native system 
		-- hides the scrollbar. If AUTOHIDE=True scrollbars are visible only if 
		-- they are necessary.
		require
			is_valid_scroll_bar(value)
		do
			iup_open.set_attribute(Current, "SCROLLBAR",value)
		end

	scroll_to (lin, col: INTEGER)
		-- (non inheritable, write only): Scroll the text to make the given 
		-- character position visible. It uses the same format and reference of 
		-- the CARET attribute ("lin:col" starting at 1). In Windows, when 
		-- FORMATTING=True "col" is ignored.
		require
			lin > 0
			col > 0
		local
			str: STRING
		do
			str := lin.out
			str.append_string(",")
			str.append_string(col.out)
			
			iup_open.set_attribute(Current, "SCROLLTO", str)
		end

	scroll_to_pos (position: INTEGER)
		-- (non inheritable, write only): Scroll the text to make the given 
		-- character position visible. It uses the same format and reference of 
		-- the CARETPOS attribute ("pos" starting at 0). 
		require
			position >= 0
		do
			iup_open.set_attribute(Current, "SCROLLTOPOS", position.out)
		end

	set_multiline_selection (lin1, col1, lin2, col2: INTEGER)
		-- Selection interval in characters. The first position, lin or col, is 
		-- "1". Where lin1, col1, lin2 and col2 are integer numbers corresponding 
		-- to the selection's interval. col2 correspond to the character after 
		-- the last selected character.
		-- In Windows, when changing the selection the caret position is also 
		-- changed.
		-- See the Notes above if using UTF-8 strings in GTK. 
		local
			str: STRING
		do
			str := lin1.out
			str.append_string(",")
			str.append_string(col1.out)
	      str.append_string(":")
 	      str.append_string(lin2.out)
			str.append_string(",")
			str.append_string(col2.out)
	
			iup_open.set_attribute(Current, "SELECTION", str)
		end

	get_multiline_selection: TUPLE[INTEGER, INTEGER, INTEGER, INTEGER]
		-- "lin1,col1,lin2,col2" where lin1, col1, lin2 and col2 are integer 
		-- numbers corresponding to the selection's interval. col2 correspond to 
		-- the character after the last selected character.
		local
			str: STRING
			i, c: INTEGER
			pos1, pos2: STRING
			tup1, tup2: TUPLE[INTEGER, INTEGER]
			tup: TUPLE[INTEGER, INTEGER, INTEGER, INTEGER]
		do
			str := iup_open.get_attribute(Current, "SELECTION")

			if str.has(':') then
				i := str.index_of(':', 1)
				c := str.count
				
				if not i.is_equal(1) then
					pos1 := str.substring(1, i - 1)
				else
					pos1 := "0,0"
				end
				
				if not i.is_equal(c) then
					pos2 := str.substring(i + 1, c)
				else
					pos2 := "0,0"
				end

				tup1 := components_of_position(pos1)
				tup2 := components_of_position(pos2)

				tup := [tup1.integer_32_item(1), tup1.integer_32_item(2),
				        tup2.integer_32_item(1), tup2.integer_32_item(2)]
			else
				tup := [0, 0, 0, 0]
			end

			Result := tup
		end

	set_multiline_selection_pos (pos1, pos2: INTEGER)
		-- Same as set_multiline_selection but using a zero based character 
		-- index. Useful for indexing the VALUE string. See the Notes above if 
		-- using UTF-8 strings in GTK. 
		require
			pos1 >= 0
			pos2 >= 0
		local
			str: STRING
		do
			str := pos1.out
			str.append_string(":")
			str.append_string(pos2.out)
			
			iup_open.set_attribute(Current, "SELECTIONPOS", str)
		end

	get_multiline_selection_pos: TUPLE[INTEGER, INTEGER]
		-- Same as get_multiline_selection but using a zero based character index.
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "SELECTIONPOS")

			if str.has(':') then
				Result := components_of_minmax(str)
			else
				Result := [0, 0]
			end
		end

	set_tab_size (size: INTEGER)
		-- Controls the number of characters for a tab stop. Default: 8.
		require
			size >= 0
		do
			iup_open.set_attribute(Current, "TABSIZE", size.out)
		end

	get_tab_size: INTEGER
		-- The tab size.
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "TABSIZE")

			if str.is_integer then
				Result := str.to_integer
			end
		end

	set_visible_lines (value: INTEGER)
		-- Defines the number of visible lines for the Natural Size, this means 
		-- that will act also as minimum number of visible lines. As for SIZE you 
		-- can set to Void after map to use it as an initial value. Default: 1.
		require
			value >= 0
		do
			iup_open.set_attribute(Current, "VISIBLELINES", value.out)
		end

	set_word_wrap (state: BOOLEAN)
		-- If enabled will force a word wrap of lines that are greater than the 
		-- with of the control, and the horizontal scrollbar will be removed. 
		-- Default: False.
		do
			iup_open.set_attribute(Current, "WORDWRAP", boolean_to_yesno(state))
		end

	load_rtf (filename: STRING): BOOLEAN
		-- (write-only) [Windows Only]: loads formatted text from a Rich 
		-- Text Format file given its filename. Return True if file is loaded.
		local
			str: STRING
		do
			iup_open.set_attribute(Current, "LOADRTF", filename)

			str := iup_open.get_attribute(Current, "LOADRTFSTATUS")

			Result := status_to_boolean(str)
		end

	save_rtf (filename: STRING): BOOLEAN
		-- (write-only) [Windows Only]: saves formatted text to a Rich 
		-- Text Format file given its filename. Return False if file is saved.
		local
			str: STRING
		do
			iup_open.set_attribute(Current, "SAVERTF", filename)

			str := iup_open.get_attribute(Current, "SAVERTFSTATUS")

			Result := status_to_boolean(str)
		end

	-- Validations

	is_valid_scroll_bar (value: STRING): BOOLEAN
		do
			if is_yes_no(value) or
				value.is_equal("HORIZONTAL") or
				value.is_equal("VERTICAL") then
				Result := True
			else
				Result := False
			end
		end

feature {NONE}

	-- Internal

	int_multiline(act: POINTER): POINTER
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"return IupMultiLine ($act);"
      end

	status_to_boolean(str: STRING): BOOLEAN
		do
			if str.is_equal("OK") then
				Result := True
			else
				Result := False
			end
		end

end

-- The MIT License (MIT)

-- Copyright (c) 2016, 2017, 2019, 2020 by German A. Arias

-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in 
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.
